package cn.com.zetatech.loader.common.util;

import cn.com.zetatech.loader.api.exception.LoaderException;
import cn.com.zetatech.loader.common.constant.LoaderConstant;
import cn.com.zetatech.loader.common.ftp.ConnectionClient;
import cn.com.zetatech.loader.common.message.ResolverMessage;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Map;

/**
 * @author zhengbs
 */
@Slf4j
public class FileLoadUtil {

    public static long getFileSize(ResolverMessage resolverMessage, String remotePath) {
        long startTime = System.currentTimeMillis();
        log.info("<=========> 开始读取文件{}大小", remotePath);
        long fileSize = 0;
        if ("FTP".equals(resolverMessage.getType()) || "SFTP".equals(resolverMessage.getType())) {
            fileSize = ftpFileSize(resolverMessage, remotePath);
        } else {
            if (!Files.exists(Paths.get(remotePath))) {
                fileSize = 0;
            } else {
                File file = new File(remotePath);
                fileSize = file.length();
            }
        }
        log.info("<=========> 文件{}加载结束，耗时：{}ms", remotePath, System.currentTimeMillis() - startTime);
        return fileSize;
    }

    private static long ftpFileSize(ResolverMessage resolverMessage, String remotePath) {
        // 验证信息并获取SFTP连接
        ConnectionClient connectionClient = ConnectionClientUtil.getInstance().getConnectionClient(resolverMessage);
        try {
            Path path = Paths.get(remotePath);
            String dir = path.getParent().toString();
            String fileName = path.getFileName().toString();
            Map<String, Long> map = connectionClient.listFileSize(dir, Arrays.asList(fileName));
            return map.containsKey(fileName) ? map.get(fileName).longValue() : 0;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            ConnectionClientUtil.getInstance().releaseConnectionClient(resolverMessage, connectionClient);
        }
        return 0;
    }

    public static String fileLoading(ResolverMessage resolverMessage, String remotePath) {
        long startTime = System.currentTimeMillis();
        log.info("<=========> 开始加载文件{}到本地文件夹", remotePath);
        String localPath = null;
        if ("FTP".equals(resolverMessage.getType()) || "SFTP".equals(resolverMessage.getType())) {
            localPath = ftpLoading(resolverMessage, remotePath);
        } else {
            localPath = nasLoading(resolverMessage, remotePath);
        }
        log.info("<=========> 文件{}加载结束，耗时：{}ms", remotePath, System.currentTimeMillis() - startTime);
        return localPath;
    }

    public static String fileLoading(String remotePath, String folder, String serverIP, int serverPort, String userName, String password, String type) {
        long startTime = System.currentTimeMillis();
        log.info("<=========> 开始加载文件{}到本地文件夹", remotePath);
        String localPath = null;
        if ("FTP".equals(type) || "SFTP".equals(type)) {
            localPath = ftpLoading(remotePath, folder, serverIP, serverPort, userName, password, type);
        } else {
            localPath = nasLoading(folder, remotePath);
        }
        log.info("<=========> 文件{}加载结束，耗时：{}ms", remotePath, System.currentTimeMillis() - startTime);
        return localPath;
    }

    private static String ftpLoading(String remotePath, String folder, String serverIP, int serverPort, String userName, String password, String type) {
        // 验证信息并获取SFTP连接
        ConnectionClient connectionClient = ConnectionClientUtil.getInstance().getConnectionClient(serverIP, serverPort, userName, password, type);
        String localPath;
        InputStream inputStream = null;
        try {
            // 截取文件名
            String fileName = remotePath.substring(remotePath.lastIndexOf("/") + 1);
            // 将文件下载到指定目录
            localPath = LoaderConstant.Loader_Default_Running_Path + "/" + folder + "/" + fileName;
            synchronized (FileLoadUtil.class) {
                inputStream = connectionClient.get(remotePath);
                FileUtil.writeFromStream(inputStream, localPath);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new LoaderException("下载文件失败：" + e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            ConnectionClientUtil.getInstance().releaseConnectionClient(serverIP, serverPort, userName, password, connectionClient);
        }
        return localPath;
    }


    private static String ftpLoading(ResolverMessage resolverMessage, String remotePath) {
        // 验证信息并获取SFTP连接
        ConnectionClient connectionClient = ConnectionClientUtil.getInstance().getConnectionClient(resolverMessage);
        String localPath;
        InputStream inputStream = null;
        try {
            // 截取文件名
            String fileName = remotePath.substring(remotePath.lastIndexOf("/") + 1);
            // 将文件下载到指定目录
            localPath = LoaderConstant.Loader_Default_Running_Path + "/" + resolverMessage.getActuatorName() + "/" + fileName;
            synchronized (FileLoadUtil.class) {
                inputStream = connectionClient.get(remotePath);
                FileUtil.writeFromStream(inputStream, localPath);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new LoaderException("下载文件失败：" + e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            ConnectionClientUtil.getInstance().releaseConnectionClient(resolverMessage, connectionClient);
        }
        return localPath;
    }

    private static String nasLoading(ResolverMessage resolverMessage, String remotePath) {
        return nasLoading(resolverMessage.getActuatorName(), remotePath);
    }

    private static String nasLoading(String folder, String remotePath) {
        // 截取文件名
        String fileName = FileUtil.getName(remotePath);
        // 将文件下载到指定目录，/data/{eventId}/文件名
        String localPath = LoaderConstant.Loader_Default_Running_Path + "/" + folder + "/" + fileName;
        try (InputStream inputStream = new FileInputStream(remotePath);
             OutputStream outputStream = new FileOutputStream(localPath)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            throw new LoaderException("下载文件失败：" + e.getMessage());
        }
        return localPath;
    }
}
